﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using TA.JSON;
using System.ComponentModel;
using TA.Win.Utils.Design;
using System.Drawing.Design;
using TA.Turbo.Design;

namespace TA.Turbo.Controls
{
	[ParseChildren(true, "Children")]
	public abstract class BaseTreeNode : IJsonCompatible
	{
		#region PUBLIC
		#region INIT
		public BaseTreeNode()
		{

		}
		#endregion
		#region PROPS
		/// <summary>
		/// Gets the modifiable collection of children.
		/// </summary>
		[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
		[NotifyParentProperty(true)]
		[Editor(typeof(TreeNodeCollectionEditor), typeof(UITypeEditor))]
		public TreeNodeCollection Children { get { return this._children; } }
		/// <summary>
		/// Gets or sets the number of children this node can display upon request.
		/// </summary>
		[NotifyParentProperty(true)]
		[DefaultValue(0)]
		public int NumChildren { get; set; }
		/// <summary>
		/// Gets or sets the unique ID of this node which will be used whenever a concrete reference to this node is needed, for example, during LoadNodes event.
		/// </summary>
		[NotifyParentProperty(true)]
		[DefaultValue(null)]
		public string UniqueId { get; set; }
		[NotifyParentProperty(true)]
		[DefaultValue(false)]
		public bool Expanded { get; set; }
		//public bool Checked { get; set; }
		//public bool ShowCheckBox { get; set; }
		#endregion
		#endregion
		#region INTERNAL
		#region VARS
		TreeNodeCollection _children = new TreeNodeCollection();
		#endregion
		#region PROPS
		protected abstract TreeNodeType Type { get; }
		#endregion
		#region METHODS
		protected internal virtual void Render(TreeView owner, TreeNodePosition position, int level, HtmlTextWriter writer)
		{
			this.RenderBeginTag(owner, position, writer);

			this.RenderImage(owner, position, writer);

			this.RenderContents(owner, position, level, writer);

			this.RenderLoadChildren(owner, writer);

			this.RenderChildren(owner, position, level, writer);


			this.RenderEndTag(writer);
		}

		protected virtual void RenderBeginTag(TreeView owner, TreeNodePosition position, HtmlTextWriter writer)
		{
			string className = "tv_node ";
			switch (position)
			{
				case TreeNodePosition.RootFirst:
					className += "first";
					break;
				case TreeNodePosition.RootLast:
				case TreeNodePosition.SubOnly:
				case TreeNodePosition.SubLast:
					className += "last";
					break;
				case TreeNodePosition.RootRegular:
				case TreeNodePosition.SubFirst:
				case TreeNodePosition.SubRegular:
					break;
				case TreeNodePosition.RootOnly:
					className += "only";
					break;
			}
			writer.AddAttribute(HtmlTextWriterAttribute.Class, className);
			writer.RenderBeginTag(HtmlTextWriterTag.Div);
		}
		protected virtual void RenderImage(TreeView owner, TreeNodePosition position, HtmlTextWriter writer)
		{
			string image = "leaf";
			if (this.Children.Count > 0 || this.NumChildren > 0)
			{
				if (this.Expanded)
					image = "expanded";
				else
					image = "collapsed";
			}

			image = owner.Page.ClientScript.GetWebResourceUrl(typeof(BaseTreeNode), "TA.Turbo.Res.Img.TreeView.node_" + image + ".png");
			writer.AddAttribute(HtmlTextWriterAttribute.Src, image);
			writer.RenderBeginTag(HtmlTextWriterTag.Img);
			writer.RenderEndTag();
		}
		protected virtual void RenderEndTag(HtmlTextWriter writer)
		{
			writer.RenderEndTag(); // div.tv_node
		}
		protected virtual void RenderContents(TreeView owner, TreeNodePosition position, int level, HtmlTextWriter writer)
		{
			this.RenderContentsBeginTag(owner, position, writer);

			this.RenderContentsMain(owner, position, level, writer);

			this.RenderContentsEndTag(owner, position, writer);
		}
		protected virtual void RenderContentsBeginTag(TreeView owner, TreeNodePosition position, HtmlTextWriter writer)
		{
			writer.AddAttribute(HtmlTextWriterAttribute.Class, "content");
			writer.RenderBeginTag(HtmlTextWriterTag.Div);
		}
		protected abstract void RenderContentsMain(TreeView owner, TreeNodePosition position, int level, HtmlTextWriter writer);
		protected virtual void RenderContentsEndTag(TreeView owner, TreeNodePosition position, HtmlTextWriter writer)
		{
			writer.RenderEndTag(); // div.content
		}
		protected virtual void RenderChildren(TreeView owner, TreeNodePosition position, int level, HtmlTextWriter writer)
		{
			this.RenderChildrenBeginTag(owner, position, writer);
			this.RenderChildrenMain(owner, position, level, writer);
			this.RenderChildrenEndTag(owner, position, writer);
		}
		protected virtual void RenderChildrenBeginTag(TreeView owner, TreeNodePosition position, HtmlTextWriter writer)
		{
			writer.AddAttribute(HtmlTextWriterAttribute.Class, "tv_list");
			if (!this.Expanded)
			{
				writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
			}
			writer.RenderBeginTag(HtmlTextWriterTag.Div);
		}
		protected virtual void RenderChildrenMain(TreeView owner, TreeNodePosition position, int level, HtmlTextWriter writer)
		{
			for (int i = 0; i < this.Children.Count; ++i)
			{
				TreeNodePosition childPos = TreeNodePosition.SubRegular;
				if (this.Children.Count == 1)
				{
					childPos = TreeNodePosition.SubOnly;
				}
				else if (i == 0)
				{
					childPos = TreeNodePosition.SubFirst;
				}
				else if (i == this.Children.Count - 1)
				{
					childPos = TreeNodePosition.SubLast;
				}

				this.Children[i].Render(owner, childPos, level + 1, writer);
			}
		}
		private void RenderChildrenEndTag(TreeView owner, TreeNodePosition position, HtmlTextWriter writer)
		{
			writer.RenderEndTag(); // div.content
		}
		private void RenderLoadChildren(TreeView owner, HtmlTextWriter writer)
		{
			writer.AddAttribute(HtmlTextWriterAttribute.Class, "load_children");
			writer.RenderBeginTag(HtmlTextWriterTag.Div);

			writer.AddAttribute(HtmlTextWriterAttribute.Href, "");
			writer.RenderBeginTag(HtmlTextWriterTag.A);
			writer.WriteEncodedText("More ...");
			writer.RenderEndTag();

			writer.RenderEndTag();
		}
		#endregion
		#region IJsonSerializable Members
		public bool IsDirty
		{
			get
			{
				return true;
			}
		}
		public void Serialize(JsonWriter jw)
		{
			this.SerializeObject(jw);
		}
		public virtual void SerializeContents(JsonWriter jw)
		{
			jw.PropertyName("Y");
			jw.Value(this.Type);

			if (this.Children.Count > 0)
			{
				jw.PropertyName("C");
				jw.StartArray();

				foreach (BaseTreeNode n in this.Children)
				{
					n.Serialize(jw);
				}

				jw.EndArray();
			}
			else if (this.NumChildren > 0)
			{
				jw.PropertyName("N");
				jw.Value(this.NumChildren);
			}

			if (this.Expanded)
			{
				jw.PropertyName("E");
				jw.Value(this.Expanded);
			}

			if (!string.IsNullOrEmpty(this.UniqueId))
			{
				jw.PropertyName("I");
				jw.Value(this.UniqueId);
			}
		}
		#endregion
		#region IJsonDeserializable Members
		public void Deserialize(IJsonReader jr)
		{
			this.DeserializeObject(jr);
		}
		public virtual void DeserializeContent(IJsonReader jr, string propShortName)
		{
			switch (propShortName)
			{
				case "C":
					this.Children.Clear();
					this.Children.Deserialize(jr);
					break;
				case "N": this.NumChildren = (int)(long)jr.Value; break;
				case "E": this.Expanded = (bool)jr.Value; break;
				case "I": this.UniqueId = (string)jr.Value; break;
			}
		}
		#endregion
		#endregion
	}
}
